#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os
import json
import uuid
import logging
from datetime import datetime
from typing import Dict, Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile, File, Form
from fastapi.responses import FileResponse, JSONResponse

from api.models.document import GenerateQARequest, GenerateQAResponse, ErrorResponse
from api.routes.document import task_storage

# 创建路由
router = APIRouter(
    prefix="/api/qa",
    tags=["qa"],
    responses={
        404: {"model": ErrorResponse, "description": "Not found"},
        500: {"model": ErrorResponse, "description": "Server error"}
    }
)

# 获取日志记录器
logger = logging.getLogger(__name__)

# 知识问答任务存储
qa_task_storage: Dict[str, Dict[str, Any]] = {}

# 获取AI服务的依赖项
def get_ai_service():
    """获取AI服务实例"""
    from main import config
    from tasks.ai_service import AIService
    return AIService(config)

# 获取OBS上传器实例
def get_obs_uploader():
    """获取OBS上传器实例"""
    from main import config
    from image_handler.obs_uploader import OBSUploader
    return OBSUploader(config)

@router.post("/generate", response_model=GenerateQAResponse)
async def generate_qa(
    request: GenerateQARequest,
    ai_service = Depends(get_ai_service)
):
    """生成知识问答对
    
    从提供的Markdown内容生成知识问答对。
    
    Args:
        request: 生成知识问答对请求
        
    Returns:
        GenerateQAResponse: 生成的知识问答对
    """
    # 生成知识问答任务ID，仅用于文件命名和日志
    qa_task_id = str(uuid.uuid4())
    
    logger.info(f"开始生成知识问答对，ID: {qa_task_id}")
    
    try:
        # 直接使用请求中提供的Markdown内容
        markdown_content = request.markdown_content
        
        if not markdown_content:
            raise HTTPException(status_code=400, detail="缺少Markdown内容")
        
        # 根据生成方式选择不同的处理方法
        if request.generate_method == "text_split":
            # 文本分割方式 - 相对快速
            qa_pairs = await ai_service.generate_qa_by_text_split(
                markdown_content, 
                request.system_name,
                request.chunk_size,
                request.overlap
            )
        elif request.generate_method == "ai_qa":
            # AI问答生成方式 - 较慢但质量更高
            # 注意：由于是直接返回结果，这可能需要较长时间处理
            qa_pairs = await ai_service.generate_qa_by_ai(
                markdown_content, 
                request.system_name,
                chunk_size=request.chunk_size,
                overlap=request.overlap
            )
        else:
            raise HTTPException(status_code=400, detail=f"不支持的生成方式: {request.generate_method}")
        
        # 使用原始文件名或生成一个默认名
        original_file_name = f"{request.system_name}_{qa_task_id[:8]}.md" if request.system_name else f"generated_{qa_task_id[:8]}.md"
        
        # 保存问答对到文件
        qa_file = await save_qa_pairs(
            qa_pairs,
            request.system_name,
            request.source_name,
            original_file_name
        )
        
        # 保存任务信息以便后续下载
        qa_task_storage[qa_task_id] = {
            "task_id": qa_task_id,
            "file_name": original_file_name,
            "system_name": request.system_name,
            "source_name": request.source_name,
            "qa_file": qa_file,
            "qa_pairs": qa_pairs,
            "status": "completed",
            "created_at": datetime.now().isoformat(),
            "updated_at": datetime.now().isoformat()
        }
        
        logger.info(f"生成知识问答对完成，ID: {qa_task_id}，共 {len(qa_pairs)} 个问答对")
        
        return {
            "task_id": qa_task_id,
            "file_name": original_file_name,
            "system_name": request.system_name,
            "source_name": request.source_name,
            "qa_pairs": qa_pairs
        }
    
    except Exception as e:
        logger.error(f"生成知识问答对失败: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))

@router.post("/upload-image")
async def upload_image_to_obs(
    file: UploadFile = File(...),
    obs_uploader = Depends(get_obs_uploader)
):
    """上传图片到OBS
    
    将图片上传到华为云OBS存储并返回可访问的URL。
    
    Args:
        file: 上传的图片文件
        
    Returns:
        JSONResponse: 包含图片URL的响应
    """
    try:
        if not file:
            raise HTTPException(status_code=400, detail="未提供图片文件")
            
        # 读取文件内容
        content = await file.read()
        
        # 检查文件是否为图片
        file_ext = os.path.splitext(file.filename)[1].lower()
        allowed_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
        
        if file_ext not in allowed_extensions:
            raise HTTPException(status_code=400, detail="仅支持上传图片文件")
        
        # 准备图片信息
        image_info = {
            "filename": file.filename,
            "data": content,
            "format": file_ext[1:]  # 去掉点号
        }
        
        # 上传到OBS
        image_url = await obs_uploader.upload(image_info)
        
        if not image_url:
            raise HTTPException(status_code=500, detail="图片上传失败")
        
        logger.info(f"图片已上传: {image_url}")
        
        # 返回图片URL
        return JSONResponse(
            content={
                "url": image_url,
                "filename": file.filename,
                "markdown": f"![{file.filename}]({image_url})"
            },
            status_code=200
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"上传图片失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"上传图片失败: {str(e)}")

@router.post("/new-qa-entry")
async def create_new_qa_entry():
    """创建新的空白知识问答条目
    
    Returns:
        JSONResponse: 包含空白QA条目的响应
    """
    try:
        # 创建空白QA条目
        new_qa = {
            "Q": "",
            "A": "",
            "source": "用户创建"
        }
        
        return JSONResponse(
            content=new_qa,
            status_code=200
        )
        
    except Exception as e:
        logger.error(f"创建新QA条目失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"创建新QA条目失败: {str(e)}")

@router.get("/download/{qa_task_id}")
async def download_qa_json(qa_task_id: str):
    """下载知识问答对JSON文件
    
    Args:
        qa_task_id: 知识问答任务ID
        
    Returns:
        FileResponse: JSON文件响应
    """
    if qa_task_id not in qa_task_storage:
        raise HTTPException(status_code=404, detail="找不到指定的知识问答任务")
    
    task_data = qa_task_storage[qa_task_id]
    
    if not task_data.get("qa_file") or not os.path.exists(task_data["qa_file"]):
        raise HTTPException(status_code=404, detail="找不到知识问答文件")
    
    return FileResponse(
        task_data["qa_file"],
        filename=os.path.basename(task_data["qa_file"]),
        media_type="application/json"
    )

@router.get("/list")
async def list_qa_tasks(
    limit: int = Query(20, description="返回的最大任务数量")
):
    """列出知识问答任务
    
    Args:
        limit: 返回的最大任务数量
        
    Returns:
        List: 任务列表
    """
    tasks = []
    
    for task_id, task_data in qa_task_storage.items():
        task_info = {
            "task_id": task_id,
            "file_name": task_data.get("file_name"),
            "system_name": task_data.get("system_name"),
            "source_name": task_data.get("source_name"),
            "qa_pairs_count": len(task_data.get("qa_pairs", [])),
            "created_at": task_data.get("created_at", datetime.now().isoformat())
        }
        tasks.append(task_info)
    
    # 按创建时间排序并限制数量
    tasks.sort(key=lambda x: x.get("created_at", ""), reverse=True)
    return tasks[:limit]

@router.get("/result/{qa_task_id}")
async def get_qa_task_result(
    qa_task_id: str,
    limit: int = Query(100, description="返回的最大问答对数量"),
    offset: int = Query(0, description="问答对偏移量")
):
    """获取知识问答任务结果
    
    Args:
        qa_task_id: 知识问答任务ID
        limit: 返回的最大问答对数量
        offset: 问答对偏移量
        
    Returns:
        Dict: 任务结果信息
    """
    if qa_task_id not in qa_task_storage:
        raise HTTPException(status_code=404, detail="找不到指定的知识问答任务")
    
    task_data = qa_task_storage[qa_task_id]
    qa_pairs = task_data.get("qa_pairs", [])
    
    return {
        "task_id": qa_task_id,
        "file_name": task_data.get("file_name"),
        "system_name": task_data.get("system_name"),
        "source_name": task_data.get("source_name"),
        "total_qa_pairs": len(qa_pairs),
        "qa_pairs": qa_pairs[offset:offset+limit]
    }

async def save_qa_pairs(
    qa_pairs: List[Dict[str, str]],
    system_name: str,
    source_name: str,
    original_file: str
) -> str:
    """保存问答对到JSON文件
    
    Args:
        qa_pairs: 问答对列表
        system_name: 系统名称
        source_name: 来源名称
        original_file: 原始文件名
        
    Returns:
        str: 保存的JSON文件路径
    """
    # 创建输出目录
    output_dir = "output"
    os.makedirs(output_dir, exist_ok=True)
    
    # 生成输出文件名
    base_name = os.path.splitext(original_file)[0]
    output_file = os.path.join(output_dir, f"{base_name}_qa.json")
    
    # 构建保存的数据
    data = {
        "original_file": original_file,
        "system_name": system_name,
        "source_name": source_name,
        "generated_at": datetime.now().isoformat(),
        "qa_count": len(qa_pairs),
        "qa_pairs": qa_pairs
    }
    
    # 保存为JSON文件
    with open(output_file, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
    
    logger.info(f"已保存知识问答对文件: {output_file}")
    
    return output_file 